/*
 * gx18b20.c
 *
 *  Created on: 2021年11月13日
 *      Author: CameronLee
 */
#include <GX18B20/gx18b20.h>


/***************************** API *******************************/

uint8_t GX18B20_GPIO_IN(GX18B20_NUM which_GX18B20)
{
	uint8_t data;
	switch (which_GX18B20) {
			case Env_GX18B20:
				data = HAL_GPIO_ReadPin(EnvTemp_GPIO_Port, EnvTemp_Pin);

				break;
			case Box_GX18B20:
				data = HAL_GPIO_ReadPin(BoxTemp_GPIO_Port,BoxTemp_Pin);

				break;
			default:
				break;
		}
	return data;
}

void GX18B20_GPIO_OUT(GX18B20_NUM which_GX18B20,GPIO_PinState out_data)
{
	switch (which_GX18B20) {
				case Env_GX18B20:

					HAL_GPIO_WritePin(EnvTemp_GPIO_Port, EnvTemp_Pin,out_data);
					break;
				case Box_GX18B20:
					HAL_GPIO_WritePin(BoxTemp_GPIO_Port, BoxTemp_Pin,out_data);

					break;
				default:
					break;
			}

}


void GX18B20_GPIO_MODE_IN(GX18B20_NUM which_GX18B20)
{

	GPIO_InitTypeDef GPIO_InitStruct;

	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull = GPIO_PULLUP;

	switch(which_GX18B20)
	{
		case Env_GX18B20:
			GPIO_InitStruct.Pin =EnvTemp_Pin;
			HAL_GPIO_Init(EnvTemp_GPIO_Port, &GPIO_InitStruct);

			break;
		case Box_GX18B20:
			GPIO_InitStruct.Pin =BoxTemp_Pin;
			HAL_GPIO_Init(BoxTemp_GPIO_Port, &GPIO_InitStruct);

			break;
		default:
			break;
	}

}

void GX18B20_GPIO_MODE_OUT(GX18B20_NUM which_GX18B20)
{
	GPIO_InitTypeDef GPIO_InitStruct;

	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

	switch(which_GX18B20) {
			case Env_GX18B20:
				GPIO_InitStruct.Pin =EnvTemp_Pin;
				HAL_GPIO_Init(EnvTemp_GPIO_Port, &GPIO_InitStruct);

				break;
			case Box_GX18B20:
				GPIO_InitStruct.Pin =BoxTemp_Pin;
				HAL_GPIO_Init(BoxTemp_GPIO_Port, &GPIO_InitStruct);

				break;
			default:
				break;
	}

}
/*微妙级别延时函数位DWT，移植的时候一并*/

/*********************** end      API       *******************/

/******移植时 下面无需更改 ***************/

/**********************    CMD Function **********************/
/*功能：向GX18B20发送一个复位信号*/
void GX18B20_Rst(GX18B20_NUM which_GX18B20)
{
	GX18B20_GPIO_MODE_OUT(which_GX18B20);
	GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_RESET); //拉低总线480~960 us ，对 GX18B20 芯片进行复位
	DWT_Delay_us(480);
	GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_SET);
	DWT_Delay_us(15);         //释放总线15~60 us
}

uint8_t GX18B20_Answer_Check(GX18B20_NUM which_GX18B20)
{
	uint8_t data_in;
    uint8_t delay = 0;
    GX18B20_GPIO_MODE_IN(which_GX18B20); // 主机设置为上拉输入
    // 等待应答脉冲（一个60~240us的低电平信号 ）的到来
    // 如果100us内，没有应答脉冲，退出函数，注意：从机接收到主机的复位信号后，会在15~60us后给主机发一个存在脉冲
    data_in = GX18B20_GPIO_IN(which_GX18B20);
    while (data_in&&(delay < 100)){
        delay++;
        DWT_Delay_us(1);
        data_in = GX18B20_GPIO_IN(which_GX18B20);
    }
    // 经过100us后，如果没有应答脉冲，退出函数
    if (delay >= 100)
        return 1;
    else
        delay = 0;
    // 有应答脉冲，且存在时间不超过240us
    while ((!data_in)&&(delay < 240)){
        delay++;
        DWT_Delay_us(1);
        data_in = GX18B20_GPIO_IN(which_GX18B20);
    }
    if (delay >= 240)
        return 1;
    return 0;
}



uint8_t GX18B20_Init(GX18B20_NUM which_GX18B20)
{

	GX18B20_Rst(which_GX18B20);
	return GX18B20_Answer_Check(which_GX18B20);
}
/********************end of CMD Function *********************/




/********************************读写操作***********************/
/*          读一个位             */
uint8_t GX18B20_Read_Bit(GX18B20_NUM which_GX18B20)
{
	uint8_t data= 0;
    GX18B20_GPIO_MODE_OUT(which_GX18B20);  //输出模式
    GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_RESET); // 读时间的起始：必须由主机产生 >1us <15us 的低电平信号
    DWT_Delay_us(5);
    GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_SET);
    DWT_Delay_us(12);
    GX18B20_GPIO_MODE_IN(which_GX18B20);// 设置成输入，释放总线，由外部上拉电阻将总线拉高
    data = GX18B20_GPIO_IN(which_GX18B20);
    return data;
}

/*          读一个字节             */
uint8_t GX18B20_Read_Byte(GX18B20_NUM which_GX18B20)
{
    uint8_t i, j, data;
    data = 0;
   for (i = 0; i < 8; i++)
   {
       j = GX18B20_Read_Bit(which_GX18B20);
       data = (data) | (j << i);
   }
    return data;
}


// 写1位到GX18B20
void GX18B20_Write_Bit(GX18B20_NUM which_GX18B20,uint8_t dat)
{
   GX18B20_GPIO_MODE_OUT(which_GX18B20);

    if (dat)
    {
       GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_RESET);// Write 1
       DWT_Delay_us(2);
       GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_SET);
       DWT_Delay_us(60);
    }
    else
    {
      GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_RESET);// Write 0
      DWT_Delay_us(60);
      GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_SET);
      DWT_Delay_us(2);
    }
}

// 写1字节到GX18B20
void GX18B20_Write_Byte(GX18B20_NUM which_GX18B20,uint8_t dat)
{
    uint8_t j;
    uint8_t testb;
    GX18B20_GPIO_MODE_OUT(which_GX18B20);
    for (j = 1; j <= 8; j++)
    {
       testb = dat & 0x01;
        dat = dat >> 1;

        if (testb)  {
        	GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_RESET);// Write 1
		    DWT_Delay_us(2);
		    GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_SET);
		    DWT_Delay_us(60);
         }
        else  {
        	GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_RESET);// Write 0
        	DWT_Delay_us(60);
			GX18B20_GPIO_OUT(which_GX18B20,GPIO_PIN_SET);
			DWT_Delay_us(2);
         }

    }
}
/********************************end 读写操作***********************/



/***************************** 温度读取  ***************************/

void GX18B20_Begin(GX18B20_NUM which_GX18B20)
{
	GX18B20_Rst(which_GX18B20);
    while(GX18B20_Answer_Check(which_GX18B20)){
    	UNUSED(which_GX18B20);
    	//错误代码
	}
    GX18B20_Write_Byte(which_GX18B20,0xcc);// skip rom
    GX18B20_Write_Byte(which_GX18B20,0x44);// convert
}

//中间要间隔750ms cpu可去执行其他
float GX18B20_Get_Temp(GX18B20_NUM which_GX18B20)
{

    uint8_t TL, TH;
    short Temperature;
    float Temperature1;

    GX18B20_Rst(which_GX18B20);
    while(GX18B20_Answer_Check(which_GX18B20)){
    	UNUSED(which_GX18B20);
	  //错误代码
	}
	GX18B20_Write_Byte(which_GX18B20,0xcc);
	GX18B20_Write_Byte(which_GX18B20,0xBE);

	TL = GX18B20_Read_Byte(which_GX18B20); // LSB
	TH = GX18B20_Read_Byte(which_GX18B20); // MSB
    if (TH > 7)  // 0000 0111 为MSB的最大值  超过这个即为负数
    {
        //flag=1;  温度为负数
        Temperature = (TH << 8) | TL;
        Temperature1 = (~Temperature) + 1;
        Temperature1 *= 0.0625;
    }
    else
    {
       //flag=0;  温度为正数
        Temperature1 = ((TH << 8) | TL)*0.0625;
    }

    return Temperature1;
}


/**************************end 温度读取  ***************************/













